/*
 * Copyright 2011-2012 Redia A/S
 * 
 * This file is part of Redias Library App for Android.
 *
 *  Redia Library App for Android is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Redia Library App for Android is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with Redia Library App for Android.  If not, see <http://www.gnu.org/licenses/>.
 */
package dk.redia.libraryapp.model;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;

import dk.redia.lib.log.Log;
import android.widget.Toast;
import dk.redia.lib.utils.AppApplication;
import dk.redia.lib.utils.AppConfiguration;
import dk.redia.lib.xmlrpc.XmlRpcClientResultListener;
import dk.redia.lib.xmlrpc.XmlRpcResultDumper;
import dk.redia.lib.xmlrpc.XmlRpcResultUtils;
import dk.redia.libraryapp.R;
import dk.redia.libraryapp.xmlrpc.library.XmlRpcClient;

public class LibraryModel {

	private static LibraryModel instance = null;
	private static final String logTag = "LibraryModel";
	private List<Library> libraries;
	private static Date lastLibraryCacheUpdateTime = new Date(0L);

//	private List<Reservation> reservations;
//	private List<Loan> loans;
//	private List<Library> libraries;
	
	public static LibraryModel getInstance() {
		if (instance==null) {
			instance = new LibraryModel();
		}
		return instance;
	}
	
	private LibraryModel() {
		libraries = new ArrayList<Library>();
//		loans = new ArrayList<Loan>();
//		reservations = new ArrayList<Reservation>();
//		libraries = new ArrayList<Library>();
	}
	
	
//	private boolean cacheOk(List<?> coll, int offset, int count) {
//		for (int i=0;i<count;i++) {
//			int idx = i + offset;
//			if (idx>=coll.size() || coll.get(idx)==null) {
//				return false;
//			}
//		}
//		return true;
//	}
	
//	private boolean loansCacheOk(int offset, int count) {
//		return cacheOk(loans, offset, count);
//	}
	
//	private boolean reservationsCacheOk(int offset, int count) {
//		return cacheOk(reservations, offset, count);
//	}
	
	private boolean librariesCacheOk() {
		Calendar cal = new GregorianCalendar();
		cal.setTime(lastLibraryCacheUpdateTime);
		cal.add(Calendar.MINUTE, 30);
		Date cacheExpireTime = cal.getTime();
		Date currentTime = new GregorianCalendar().getTime();
		
		Log.d(logTag, "Library list cache expires at: " + cacheExpireTime);
		Log.d(logTag, "Current time is: " + currentTime);
		Log.d(logTag, "Last library cache update at: " + lastLibraryCacheUpdateTime);
		
		if (libraries==null) {
			return false;
		}
		if (libraries.size()<=0) {
			return false;
		}
		if (currentTime.after(cacheExpireTime)) {
			return false;
		}
		return true;
	}

	public void getLibraries(final LibraryModelListener l) {
		if (librariesCacheOk()) {
			Log.d(logTag, "Using cached library list");
			l.getLibrariesResult(this.libraries);			
		} else {
		    XmlRpcClient.getInstance().getLibraryListData(
		    		AppConfiguration.getInstance().getCustomerId(),
		    		AppConfiguration.getInstance().getApiKey(), new XmlRpcClientResultListener() {
				public void callFailed(String message) {
					Log.e(LibraryModel.logTag, "Failed to retrieve libary list data: " + message);
					AppApplication.toast(R.string.failedToRetrieveLibraryListText, Toast.LENGTH_LONG);
				}
				
				public void callCompleted(Object result) {
					XmlRpcResultDumper.dump(result);
					Map<String, Object> resultMap = XmlRpcResultUtils.unpackStandardResult(result);
					Map<String, Object> dataMap = XmlRpcResultUtils.unpackStruct(resultMap.get("data"));
					if (dataMap!=null) {
						List<Library> ls = new ArrayList<Library>();
						for (String libraryId : dataMap.keySet()) {
							Map<String, Object> libraryMap = XmlRpcResultUtils.unpackStruct(dataMap.get(libraryId));
							if (libraryMap!=null) {
								Library l = Library.fromMap(libraryMap);
								if (l!=null) {
									ls.add(l);
									Log.d(LibraryModel.logTag, "Found library: " + l.getName());
								} else {
									Log.d(LibraryModel.logTag, "Failed to create Library object from map for library with id " + libraryId);
								}
							} else {
								Log.d(LibraryModel.logTag, "Failed to unpack library data for library with id " + libraryId);
							}
						}
						LibraryModel.lastLibraryCacheUpdateTime = new GregorianCalendar().getTime();
						Collections.sort(ls);
						libraries = ls;
						l.getLibrariesResult(ls);
					} else {
						Log.d(LibraryModel.logTag, "Failed to unpack library list object");
						l.getLibrariesFailure("Failed to retrieve library list");
					}
				}
			});
		}
	}
}
